import Taro from '@tarojs/taro';

// 定义错误类型
interface RequestError {
  message: string;
  code?: number;
  data?: any;
}

// 定义请求选项
interface RequestOptions {
  method?:
    | 'GET'
    | 'POST'
    | 'PUT'
    | 'DELETE'
    | 'OPTIONS'
    | 'HEAD'
    | 'TRACE'
    | 'CONNECT';
  data?: any;
  header?: Record<string, string>;
  timeout?: number;
}

const request = <T = any>(
  url: string,
  options: RequestOptions = {}
): Promise<[RequestError, null] | [null, T]> => {
  const { method = 'GET', data = {}, header = {}, timeout = 10000 } = options;

  return new Promise(resolve => {
    Taro.request({
      url,
      method,
      data,
      header: {
        'Content-Type': 'application/json',
        ...header,
      },
      timeout,
      success: res => {
        if (res.statusCode >= 200 && res.statusCode < 300) {
          // 请求成功
          resolve([null, res.data as T]);
        } else {
          // HTTP状态码错误
          resolve([
            {
              message:
                res.data?.message || `请求失败，状态码：${res.statusCode}`,
              code: res.statusCode,
              data: res.data,
            },
            null,
          ]);
        }
      },
      fail: error => {
        // 请求失败（网络错误等）
        resolve([
          {
            message: error.errMsg || '网络请求失败',
            code: -1,
          },
          null,
        ]);
      },
    });
  });
};

// 请求方法别名
const getRequest = <T = any>(
  url: string,
  data?: any,
  options?: Partial<RequestOptions>
): Promise<[RequestError | null, T | null]> => {
  return request<T>(url, { data, method: 'GET', ...options });
};

const postRequest = <T = any>(
  url: string,
  data?: any,
  options?: Partial<RequestOptions>
): Promise<[RequestError | null, T | null]> => {
  return request<T>(url, { data, method: 'POST', ...options });
};

const putRequest = <T = any>(
  url: string,
  data?: any,
  options?: Partial<RequestOptions>
): Promise<[RequestError | null, T | null]> => {
  return request<T>(url, { data, method: 'PUT', ...options });
};

const deleteRequest = <T = any>(
  url: string,
  data?: any,
  options?: Partial<RequestOptions>
): Promise<[RequestError | null, T | null]> => {
  return request<T>(url, { data, method: 'DELETE', ...options });
};

export { request, getRequest, postRequest, putRequest, deleteRequest };
